package com.yz.sharkim.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yz.sharkim.entity.User;
import com.yz.sharkim.exception.WebSocketAuthorityException;
import com.yz.sharkim.mapper.UserMapper;
import com.yz.sharkim.service.IUserService;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.stereotype.Service;
import org.springframework.util.IdGenerator;
import org.springframework.util.SimpleIdGenerator;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yangzheng
 * @version 1.0
 * @date 2019/11/5
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    /**
     * key channel.id()
     * value User
     */
    private static final Map<Integer, User> USER_CACHE = new ConcurrentHashMap<>();

    public static final AttributeKey<Integer> NETTY_CHANNEL_KEY = AttributeKey.valueOf("USER_ID");

    @Override
    public User getUserById(Integer id) {
        return USER_CACHE.get(id);
    }

    @Override
    public User getUserByChannel(Channel channel) {
        val key = channel.attr(NETTY_CHANNEL_KEY);
        if (key != null && key.get() != null) {
            return USER_CACHE.get(key.get());
        }
        return null;
    }

    @Override
    public void online(Channel channel, User user) {
        synchronized (channel) {
            user.setChannel(channel);
            val key = channel.attr(NETTY_CHANNEL_KEY);
            if (key.get() != null) {
                USER_CACHE.remove(key.get());
            }
            key.set(user.getId());
            USER_CACHE.put(user.getId(), user);
            log.info("User count {}.", USER_CACHE.size());
        }
    }


    @Override
    public void offline(Integer id) {
        USER_CACHE.remove(id);
    }

    @Override
    public List<User> getUserList() {
        return new ArrayList<>(USER_CACHE.values());
    }

    @Override
    public Integer getNo(Integer id) {
        val user = USER_CACHE.get(id);
        user.getUserNo().incrementAndGet();
        return user.getUserNo().get();
    }

    @Override
    public Integer getNo(Channel channel) {
        val key = channel.attr(NETTY_CHANNEL_KEY);
        if (key == null) {
            throw new WebSocketAuthorityException();
        }
        return getNo(key.get());
    }

}
